<!--
 * @Description: 消息条
 * @Author: James324
 * @Date: 2023-12-18 10:56:16
 * @LastEditors: James324
 * @LastEditTime: 2023-12-26 16:25:52
-->
<script setup lang="ts">
interface Props {
    modelValue: boolean; // 控制显示消息条
    showArrow?: boolean; // 是否显示三角形
    text?: string; // 消息条内容文案
    flip?: boolean; // 消息条是否溢出窗口
    buttonTitle?: string; // 按钮文案
    showButton?: boolean; // 是否显示按钮
    duration?: number; // 自动关闭时间, 单位 ms
    autoClose?: boolean; // 是否自动关闭
    showMask?: boolean; // 是否显示遮罩层
}
const props = withDefaults(defineProps<Props>(), {
    modelValue: false,
    showArrow: false,
    text: "Hello, I'm a snackbar",
    flip: false,
    buttonTitle: '我知道了',
    showButton: true,
    duration: 3000,
    autoClose: true,
    showMask: false
});
const emit = defineEmits(['update:modelValue', 'ok']);

defineOptions({
    inheritAttrs: false
});

const snackbar = ref();

let clearEnter: any;
let clearLeave: any;
let clearScroll: any;
onMounted(() => {
    clearEnter = useEventListener(snackbar.value, 'mouseenter', handleMouseEnter);
    clearLeave = useEventListener(snackbar.value, 'mouseleave', handleMouseLeave);
    clearScroll = useEventListener(window, 'scroll', handleMouseScroll);
});

onUnmounted(() => {
    clearEnter();
    clearLeave();
    clearScroll();
});

const handleMouseEnter = () => {
    if (timer) clearTimeout(timer);
    emit('update:modelValue', true);
};

const handleMouseLeave = () => {
    if (props.autoClose) {
        handleAutoClose();
    }
};

const attrs = useAttrs();
const handleMouseScroll = () => {
    if (props.showArrow && attrs.style) {
        if (timer) clearTimeout(timer);
        emit('update:modelValue', false);
    }
};

watch(
    () => props.modelValue,
    (visible: boolean) => {
        if (props.autoClose && visible) {
            handleAutoClose();
        }
        if (props.showMask) maskVisible.value = visible;
    }
);

let timer: any;
const handleAutoClose = () => {
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
        emit('update:modelValue', false);
    }, props.duration);
};

const maskVisible = ref(false);

const handleOk = () => {
    emit('update:modelValue', false);
    emit('ok');
};
</script>

<template>
    <div>
        <Teleport to="body">
            <transition name="fade" mode="out-in">
                <div
                    v-show="modelValue"
                    id="snackbar"
                    ref="snackbar"
                    :class="[
                        'm-snackbar__wrapper',
                        {
                            'is-arrow': showArrow,
                            'is-dynamic': $attrs.style && ($attrs.style as any)?.left,
                            'is-flip': flip
                        }
                    ]"
                    v-bind="$attrs"
                >
                    <div class="m-snackbar__content">{{ text }}</div>
                    <div v-if="showButton" class="m-snackbar__actions">
                        <span class="m-btn__content" @click="handleOk">{{ buttonTitle }}</span>
                    </div>
                </div>
            </transition>
        </Teleport>
        <q-mask v-if="showMask" v-model="maskVisible" :mask="false" theme="light" />
    </div>
</template>

<style lang="scss" scoped>
@include b(m-snackbar) {
    @include e(wrapper) {
        --q-shadow-key-umbra-opacity: rgb(0 0 0 / 20%);
        --q-shadow-key-penumbra-opacity: rgb(0 0 0 / 12%);
        --q-snack-bg-primary: rgb(48 65 86);

        position: fixed;
        left: 50%;
        z-index: 3334;
        display: flex;
        align-items: center;
        min-width: 344px;
        max-width: 672px;
        min-height: 48px;
        padding: 0;
        color: rgb(238 238 238);
        background: var(--q-snack-bg-primary);
        border-radius: 4px;
        box-shadow:
            0 3px 5px -1px var(--q-shadow-key-umbra-opacity, rgb(0 0 0 / 20%)),
            0 6px 10px 0 var(--q-shadow-key-penumbra-opacity, rgb(0 0 0 / 14%)),
            0 1px 18px 0 var(--q-shadow-key-penumbra-opacity, rgb(0 0 0 / 12%));
        transform: translateX(-50%);

        &:not(.is-dynamic) {
            bottom: 30px;
        }

        @include when(arrow) {
            &::after {
                position: absolute;
                top: -5px;
                left: 24px;
                display: block;
                width: 10px;
                height: 10px;
                content: '';
                background: var(--q-snack-bg-primary);
                border: 1px solid var(--q-snack-bg-primary);
                transform: rotate(45deg);
            }
        }

        // 是否动态设置 left
        @include when(dynamic) {
            transform: none;
        }

        @include when(flip) {
            &::after {
                left: 92%;
            }
        }
    }

    @include e(content) {
        flex-grow: 1;
        padding: 14px 16px;
        margin-right: auto;
        font-size: 14px;
        font-weight: 400;
        text-align: initial;
    }

    @include e(actions) {
        margin-right: 8px;
    }
}

@include b(m-btn) {
    @include e(content) {
        min-width: auto;
        height: 36px;
        padding: 0 8px;
        font-family: sans-serif;
        font-size: 14px;
        font-weight: 500;
        color: #e91e63;
        text-transform: uppercase;
        letter-spacing: 1.25px;
        cursor: pointer;
    }
}
</style>
